/*
 * @(#)JarNode.java $version 2012-3-2
 * 
 * Copyright 2011 RogueDevelopment Gruop. All rights Reserved.
 * ROGUEDEVELOPMENT PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.nadostar.extensions.util;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @author LEESUNG
 * 
 */
public class JarNode extends Node<JarEntry, JarNode> implements Resource {
	private JarFile source;

	/**
	 * Instantiates a new jar node.
	 * 
	 * @param source
	 *            the source
	 */
	public JarNode(JarFile source) {
		super("root");
		this.source = source;
	}

	/**
	 * Instantiates a new jar node.
	 * 
	 * @param name
	 *            the name
	 */
	public JarNode(String name) {
		super(name);
	}

	/**
	 * Instantiates a new jar node.
	 * 
	 * @param name
	 *            the name
	 * @param value
	 *            the value
	 */
	public JarNode(String name, JarEntry value) {
		super(name, value);
	}

	/**
	 * Source.
	 * 
	 * @return the jar file
	 */
	public JarFile source() {
		return source == null ? parent().source() : source;
	}

	/**
	 * @see com.nhncorp.lucy.common.util.Resource#children() {@inheritDoc}
	 */
	public Collection<Resource> children() {
		List<Resource> resources = new LinkedList<Resource>();

		for (JarNode child : children.values()) {
			resources.add(child);
		}

		return resources;
	}

	/**
	 * @see com.nhncorp.lucy.common.util.Resource#resource() {@inheritDoc}
	 */
	public URL resource() throws MalformedURLException {
		return new URL(toString());
	}

	/**
	 * @see com.nhncorp.lucy.common.util.Resource#openStream() {@inheritDoc}
	 */
	public InputStream openStream() throws Exception {
		return resource().openStream();
	}

	/**
	 * @see com.nhncorp.lucy.common.util.Resource#terminal() {@inheritDoc}
	 */
	public boolean terminal() {
		return !isRoot() && !value().isDirectory();
	}

	/**
	 * @see com.nhncorp.lucy.common.util.Node#create(java.lang.String,
	 *      java.lang.Object) {@inheritDoc}
	 */
	@Override
	protected JarNode create(String name, JarEntry value) {
		return new JarNode(name, value);
	}

	/**
	 * Builds the.
	 * 
	 * @param source
	 *            the source
	 * 
	 * @return the jar node
	 * 
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	public static JarNode build(JarFile source) throws IOException {
		JarNode root = new JarNode(source);
		try {
			Enumeration<JarEntry> entries = source.entries();

			while (entries.hasMoreElements()) {
				JarEntry entry = entries.nextElement();
				root.createRecursive(entry.getName(), entry);
			}

			return root;
		} finally {
			source.close();
		}
	}

	/**
	 * @see java.lang.Object#toString() {@inheritDoc}
	 */
	public String toString() {
		return isRoot() ? "file:/" + source().getName() : "jar:file:/"
				+ source().getName() + "!/" + value().getName();
	}

	/**
	 * @see java.lang.Object#equals() {@inheritDoc}
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}

		if (!(obj instanceof JarNode)) {
			return false;
		}

		return this.source().equals(((JarNode) obj).source());
	}

	/**
	 * @see java.lang.Object#hashCode() {@inheritDoc}
	 */
	@Override
	public int hashCode() {
		return this.source() != null ? this.source().hashCode() : this
				.hashCode();
	}
}
